package com.raycloud.robot.utils;

import com.raycloud.bizlogger.log.FullInfoBizLog;
import java.lang.reflect.Field;
import java.util.concurrent.ThreadFactory;
import java.util.Iterator;
import org.apache.commons.lang.StringUtils;
import com.alibaba.dubbo.common.utils.NamedThreadFactory;
import java.util.Objects;
import java.util.concurrent.ExecutorService;
import java.util.Map;
import com.alibaba.dubbo.common.Constants;
import com.alibaba.dubbo.common.extension.ExtensionLoader;
import com.alibaba.dubbo.common.store.DataStore;
import com.raycloud.robot.enums.EnumThreadPoolType;
import java.util.concurrent.ThreadPoolExecutor;
import com.raycloud.bizlogger.Logger;

public class LogUtils{
    private static final Logger dubboThreadPoolLogger;
    private static final Logger knThreadPoolLogger;
    public static void knThreadPoolLog(final ThreadPoolExecutor result,final EnumThreadPoolType threadPoolType){
        commonThreadPoolLog(result,"",result.getMaximumPoolSize()/2,result.getMaximumPoolSize()/4*3,null,threadPoolType);
    }
    public static void dubboThreadPoolLog() throws NoSuchFieldException,IllegalAccessException{
        final DataStore dataStore=(DataStore)ExtensionLoader.getExtensionLoader((Class)DataStore.class).getDefaultExtension();
        final Map<String,Object> executors=dataStore.get(Constants.EXECUTOR_SERVICE_COMPONENT_KEY);
        for(final Map.Entry<String,Object> entry : executors.entrySet()){
            final String port=entry.getKey();
            final ExecutorService executor=entry.getValue();
            if(Objects.nonNull(executor)&&executor instanceof ThreadPoolExecutor){
                final ThreadPoolExecutor tp=(ThreadPoolExecutor)executor;
                final ThreadFactory threadFactory=tp.getThreadFactory();
                if(Objects.isNull(threadFactory)){
                    continue;
                }
                if(!(threadFactory instanceof NamedThreadFactory)){
                    continue;
                }
                final NamedThreadFactory namedThreadFactory=(NamedThreadFactory)threadFactory;
                final Class factoryClass=namedThreadFactory.getClass().getSuperclass();
                final Field field=factoryClass.getDeclaredField("mPrefix");
                field.setAccessible(true);
                final String mPrefix=(String)field.get(namedThreadFactory);
                if(StringUtils.isBlank(mPrefix)){
                    continue;
                }
                if(!mPrefix.startsWith("DubboServerHandler")){
                    continue;
                }
                final String threadPoolName=mPrefix.replace("-thread-","");
                commonThreadPoolLog(tp,threadPoolName,tp.getMaximumPoolSize()/5,tp.getMaximumPoolSize()/5*2,port,EnumThreadPoolType.DUBBO_SERVER_THREAD_POOL);
            }
        }
    }
    public static Boolean commonThreadPoolLog(final ThreadPoolExecutor result,final String threadPoolName,final Integer alertCount,final Integer stackCount,final String port,final EnumThreadPoolType threadPoolType){
        final int activeCount=result.getActiveCount();
        final int maximumPoolSize=result.getMaximumPoolSize();
        final int largestPoolSize=result.getLargestPoolSize();
        final Long task=result.getTaskCount();
        final boolean alertStatus=activeCount>alertCount;
        final FullInfoBizLog.FullInfoBizLogBuilder fullInfoBizLogBuilder=FullInfoBizLog.builder().withType("status",(Object)alertStatus).withType("max",(Object)maximumPoolSize).withType("active",(Object)activeCount).withType("largest",(Object)String.valueOf(largestPoolSize)).withType("taskCount",(Object)String.valueOf(task));
        if(StringUtils.isNotBlank(port)){
            fullInfoBizLogBuilder.withType("port",(Object)port);
        }
        switch(threadPoolType){
            case COMMON_THREAD_POOL:{
                LogUtils.knThreadPoolLogger.fullInfo(fullInfoBizLogBuilder.build());
                break;
            }
            case DUBBO_SERVER_THREAD_POOL:{
                LogUtils.dubboThreadPoolLogger.fullInfo(fullInfoBizLogBuilder.build());
                break;
            }
        }
        final boolean stackStatus=activeCount>stackCount;
        if(stackStatus||alertStatus){
            DingDingUtils.sendThreadPoolMsg(maximumPoolSize,activeCount,port,threadPoolType,threadPoolName);
            if(stackStatus){
                JVMUtils.dumpJStack("");
            }
        }
        return stackStatus;
    }
    static{
        dubboThreadPoolLogger=Logger.getLogger("dubboServerHandler");
        knThreadPoolLogger=Logger.getLogger("knThreadPool");
    }
}
